/*
 * userinfo_transfer.c
 *
 *  Created on: 2013-2-6
 *      Author: panqiuhui
 */
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <pthread.h>

#include "../head/common_struct/userinfo.h"
#include "../head/communicate_with_client/userinfo_transfer.h"
#include "../head/dao/userinfo_dao.h"

//负责接受用户登录请求的线程的启动函数
void *login_thread_function(void *arg) {
	//启动线程
	int port = *(int *) arg;

	int server_socketfd, client_socketfd;
	int server_len, client_len;
	struct sockaddr_in server_address;
	struct sockaddr_in client_address;
	int result;
	int maxfd;
	fd_set readfds, tempfds;

	server_socketfd = socket(AF_INET, SOCK_STREAM, 0);

	server_address.sin_family = AF_INET;
	server_address.sin_addr.s_addr = htonl(INADDR_ANY );
	server_address.sin_port = htons(port);
	server_len = sizeof(server_address);

	bind(server_socketfd, (struct sockaddr *) &server_address, server_len);

	listen(server_socketfd, 5);

	FD_ZERO(&readfds);
	FD_SET(server_socketfd, &readfds);
	maxfd = server_socketfd;

	printf("login_thread start.\n");

	while (true) {
		int fd;
		int nread;

		tempfds = readfds;

		printf("login_thread server waiting\n");
		result = select(maxfd + 1, &tempfds, NULL, NULL, NULL );

		if (result < 1) {
			perror("userinfo_transfer.c: error\n");
			break;
		}

		for (fd = 0; fd <= maxfd; fd++) {
			if (FD_ISSET(fd,&tempfds)) {
				if (fd == server_socketfd) {
					client_len = sizeof(client_address);
					client_socketfd = accept(server_socketfd,
							(struct sockaddr*) &client_address,
							(socklen_t*) &client_len);
					FD_SET(client_socketfd, &readfds);
					if (client_socketfd > maxfd) {
						maxfd = client_socketfd;
					}
					printf("login_thread add client on fd %d\n",
							client_socketfd);
				} else {
					ioctl(fd, FIONREAD, &nread);
					if (nread == 0) {
						close(fd);
						FD_CLR(fd, &readfds);
						printf("login_thread remove client in fd %d\n", fd);
					} else {
						struct login_request request;
						read(fd, &request, sizeof(request));
						struct userinfo user;
						bool check_result = true;
						check_result = islogin(&request, &user);
						write(fd, &check_result, sizeof(check_result));
						if (check_result) {
							write(fd, &user, sizeof(user));
						}
					}
				}
			}
		}
	}
	pthread_exit("login_thread exit failure!");
}

//负责接受编辑个人资料和注册请求的线程的启动函数
void *userinfo_thread_function(void *arg) {
	//启动线程
	int port = *(int *) arg;

	int server_socketfd, client_socketfd;
	int server_len, client_len;
	struct sockaddr_in server_address;
	struct sockaddr_in client_address;
	int result;
	int maxfd;
	fd_set readfds, tempfds;

	server_socketfd = socket(AF_INET, SOCK_STREAM, 0);

	server_address.sin_family = AF_INET;
	server_address.sin_addr.s_addr = htonl(INADDR_ANY );
	server_address.sin_port = htons(port);
	server_len = sizeof(server_address);

	bind(server_socketfd, (struct sockaddr *) &server_address, server_len);

	listen(server_socketfd, 5);

	FD_ZERO(&readfds);
	FD_SET(server_socketfd, &readfds);
	maxfd = server_socketfd;

	printf("userinfo_thread start.\n");

	while (true) {
		int fd;
		int nread;

		tempfds = readfds;

		printf("userinfo_thread server waiting\n");
		result = select(maxfd + 1, &tempfds, NULL, NULL, NULL );

		if (result < 1) {
			perror("userinfo_transfer.c: error\n");
			break;
		}

		for (fd = 0; fd <= maxfd; fd++) {
			if (FD_ISSET(fd,&tempfds)) {
				if (fd == server_socketfd) {
					client_len = sizeof(client_address);
					client_socketfd = accept(server_socketfd,
							(struct sockaddr*) &client_address,
							(socklen_t*) &client_len);
					FD_SET(client_socketfd, &readfds);
					if (client_socketfd > maxfd) {
						maxfd = client_socketfd;
					}
					printf("userinfo_thread add client on fd %d\n",
							client_socketfd);
				} else {
					ioctl(fd, FIONREAD, &nread);
					if (nread == 0) {
						close(fd);
						FD_CLR(fd, &readfds);
						printf("userinfo_thread remove client in fd %d\n", fd);
					} else {
						struct request_type type;
						read(fd, &type, sizeof(type));
						switch (type.type) {
						case TYPE_EDIT_PERSONAL_INFO: {
							struct userinfo_request request;
							read(fd, &request, sizeof(request));
							bool update_result = true;
							update_result = update_userinfo(&request);
							write(fd, &update_result, sizeof(update_result));
							break;
						}
						case TYPE_REGISTER: {
							struct userinfo_request request;
							read(fd, &request, sizeof(request));
							bool register_result = true;
							register_result = register_new_user(&request);
							write(fd, &register_result,
									sizeof(register_result));
							break;
						}
						case TYPE_CHANGE_PASSWORD: {
							struct change_pw_request request;
							read(fd, &request, sizeof(request));
							bool change_result = true;
							change_result = change_password(&request);
							write(fd, &change_result, sizeof(change_result));
							break;
						}
						default: {
							perror("userinfo_thread request type error\n");
							break;
						}
						}
					}
				}
			}
		}
	}

	pthread_exit("userinfo_thread exit failure!");
}
